<?php

    #-------------------------------------------------------------#
	# This file is part of the Tekuna MVC Microframework for PHP. #
	# (c) 2009 Niels Jäckel <niels.jaeckel@tekuna.org>            #
	# Please visit http://tekuna.org/ for more information.       #
	#                                                             #
	# This software is licensed under the MIT License. Please     #
	# view the LICENSE file for the full text of this license.    #
    #-------------------------------------------------------------#


	class TekunaTestReporter extends HtmlReporter {

		protected
			$iCountPasses = 0,
			$iCountFailures = 0,
			$iCountExceptions = 0,

			$arrResultTree = array();


	    function __construct() {

	        $this->SimpleReporter();
	    }


	    function paintHeader($test_name) {

	        $this->sendNoCacheHeaders();

	        echo <<<EOF
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
	<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
	<head>
		<title>$test_name</title>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
		<meta name="language" content="en" />

		<style type="text/css">

			* {

				margin:0;
				padding:0;
				font-size:1em;
			}

			body {

				font-family:Verdana,Arial,Sans-serif;
				font-size:62.5%;

				padding:2em;
			}

			h1 {

				font-size:3em;
				color:#AAA;
				margin:0 0 1em 0;
			}

			div#results {

				color:white;
				font-size:1.2em;
				padding:1em;
			}

			div#results h2 {

				font-size:1.2em;
				margin:0 0 1em 0;
			}

			div#results p span {

				width:3em;
				display:block;
				float:left;
			}

			div.result_pass {

				background-color:green;
			}

			div.result_fail {

				background-color:red;
			}

			table#detailed_results {

				border-spacing:0;
				margin:2em 0;
				border:0.1em solid #BBB;
				width:100%;
			}

			table#detailed_results th {

				padding:0.3em 0.5em;
				font-size:1.2em;

				background-color:#BBB;
				text-align:left;
			}

			table#detailed_results tr.zebra {

				background-color:#EEE;
			}

			table#detailed_results tr td {

				padding:0.2em 0.5em;
				font-size:1.2em;
			}

			table#detailed_results tr .center {

				text-align:center;
			}

			table#detailed_results td.pass {

				background-color:green;
				color:white;
			}

			table#detailed_results td.fail {

				background-color:red;
				color:white;
			}

			table#detailed_results td pre {

				font-size:1.2em;
				margin:1em 0 2em 0;
			}

			a.showPasses {

				font-size:1.2em;
				display:block;
				margin:2em 0;
			}

		</style>

	</head>
	<body>

		<h1>$test_name</h1>
EOF;

	    }


		protected function getResultTableRows() {

			$sOut = '';
			$iLine = 0;

			foreach ($this -> arrResultTree as $sTestSuite => $arrTestSuite) {

				foreach ($arrTestSuite['tests'] as $sTestCase => $arrTestCase) {

					foreach ($arrTestCase['tests'] as $sTestMethod => $arrMethodResults) {

						$bIsPass = ($arrMethodResults['failures'] == 0);

						if (! $bIsPass || SHOW_TEST_PASSES) {

							$iLine++;

							$sZebraClass = (($iLine % 2 == 0) ? 'zebra' : '');
							$sPassClass = '';
							$sFailClass = '';

							if ($bIsPass) {

								$sPassClass = 'pass';
							}
							else {

								$sFailClass = 'fail';
							}

							$sOut .= "<tr class=\"$sZebraClass\">";
							$sOut .= "   <td>$sTestSuite</td>";
							$sOut .= "   <td>$sTestCase</td>";
							$sOut .= "   <td>$sTestMethod</td>";
							$sOut .= "   <td class=\"center $sPassClass\">$arrMethodResults[passes]</td>";
							$sOut .= "   <td class=\"center $sFailClass\">$arrMethodResults[failures]</td>";
							$sOut .= "</tr>";

							// print error or exception information
							if (! $bIsPass) {

								foreach ($arrMethodResults['messages'] as $sMessage) {

									$sOut .= "<tr class=\"$sZebraClass\">";
									$sOut .= "   <td colspan=\"5\"><pre>$sMessage</pre></td>";
									$sOut .= "</tr>";
								}
							}
						}
					}
				}
			}


#print_r($this -> arrResultTree);

			return $sOut;
		}


	    function paintFooter($test_name) {

			// result overview
			$sResultClass = (($this -> iCountFailures + $this -> iCountExceptions == 0) ? 'pass' : 'fail');
			$iCountTestCases = $this -> getTestCaseCount();

			// result table
			$sTableRows = $this -> getResultTableRows();

	        echo <<<EOF

		<div id="results" class="result_$sResultClass">
			<h2>Test Result</h2>

			<p>
				<span>$iCountTestCases</span> test cases<br />
				<span>$this->iCountPasses</span> passes<br />
				<span>$this->iCountFailures</span> failures<br />
				<span>$this->iCountExceptions</span> exceptions<br />
			</p>
		</div>
EOF;

			if (($this -> iCountFailures + $this -> iCountExceptions > 0) || SHOW_TEST_PASSES) {

	        echo <<<EOF
		<table id="detailed_results">
			<tr>
				<th>Main Test Suite</th>
				<th>Test Suite</th>
				<th>Method</th>
				<th class="center">Passes</th>
				<th class="center">Failures</th>
			</tr>

			$sTableRows

		</table>
EOF;
			}


	        echo <<<EOF

	        <p>
	        	<a href="?showPasses" class="showPasses">show passed tests</a>
	        </p>
	</body>
</html>
EOF;
	    }


	    protected function storeResultInformation($sTestSuite, $sTestCase, $sTestMethod, $bPass, $sMessage = '') {

			// build test array structure
			if (! isset($this -> arrResultTree[$sTestSuite])) {

				$this -> arrResultTree[$sTestSuite] = array('passes' => 0, 'failures' => 0, 'tests' => array());
			}

			if (! isset($this -> arrResultTree[$sTestSuite]['tests'][$sTestCase])) {

				$this -> arrResultTree[$sTestSuite]['tests'][$sTestCase] = array('passes' => 0, 'failures' => 0, 'tests' => array());
			}

			if (! isset($this -> arrResultTree[$sTestSuite]['tests'][$sTestCase]['tests'][$sTestMethod])) {

				$this -> arrResultTree[$sTestSuite]['tests'][$sTestCase]['tests'][$sTestMethod] = array('passes' => 0, 'failures' => 0, 'messages' => array());
			}


			// store test result message
			if (trim($sMessage) != '') {

				$this -> arrResultTree[$sTestSuite]['tests'][$sTestCase]['tests'][$sTestMethod]['messages'][] = $sMessage;
			}

			// increase counters
			if ($bPass) {

				$this -> arrResultTree[$sTestSuite]['tests'][$sTestCase]['tests'][$sTestMethod]['passes']++;
				$this -> arrResultTree[$sTestSuite]['tests'][$sTestCase]['passes']++;
				$this -> arrResultTree[$sTestSuite]['passes']++;
			}
			else {

				$this -> arrResultTree[$sTestSuite]['tests'][$sTestCase]['tests'][$sTestMethod]['failures']++;
				$this -> arrResultTree[$sTestSuite]['tests'][$sTestCase]['failures']++;
				$this -> arrResultTree[$sTestSuite]['failures']++;
			}

	    }


	    function paintPass($message) {

	        // increase pass counter
	        $this -> iCountPasses++;

			// get the pass information
			$arrTestInfo = $this -> getTestList();

			// store the information
			$this -> storeResultInformation($arrTestInfo[2], $arrTestInfo[4], $arrTestInfo[5], TRUE);
	    }


	    function paintFail($message) {

	        // increase failure counter
	        $this -> iCountFailures++;

			// get the pass information
			$arrTestInfo = $this -> getTestList();

			// store the information
			$this -> storeResultInformation($arrTestInfo[2], $arrTestInfo[4], $arrTestInfo[5], FALSE, $message);
	    }


	    function paintError($message) {

	        // increase failure counter
	        $this -> iCountExceptions++;

			// get the pass information
			$arrTestInfo = $this -> getTestList();

			// store the information
			$this -> storeResultInformation($arrTestInfo[2], $arrTestInfo[4], $arrTestInfo[5], FALSE, $message);
	    }


	    function paintException($exception) {

	        // increase failure counter
	        $this -> iCountExceptions++;

			// get the pass information
			$arrTestInfo = $this -> getTestList();

			// store the information
			$this -> storeResultInformation($arrTestInfo[2], $arrTestInfo[4], $arrTestInfo[5], FALSE, TekunaException :: getTextOutput($exception));

	    }


	    function paintSkip($message) {

	        // increase failure counter
	        $this -> iCountPasses++;

			// get the pass information
			$arrTestInfo = $this -> getTestList();

			// store the information
			$this -> storeResultInformation($arrTestInfo[2], $arrTestInfo[4], $arrTestInfo[5], TRUE, "Skipped.\n\n". $message);
	    }
	}
